// eee.Sheffield.PZ.Imaging
//
// Copyright ?Ping Zou, 2007
// sg71.cherub@gmail.com

using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using eee.Sheffield.PZ.Imaging;
using eee.Sheffield.PZ.Math;
using System.IO;


namespace eee.Sheffield.PZ.Imaging.ImageFilter
{
    public abstract class ImageFilter : IGraylevelImageFilter, IColourImageFilter
    {
        #region Field
        protected string _log;
        protected string _flag;
        protected bool _normalize = false;
        protected ConvertBitmapMatrix _converter = new ConvertBitmapMatrix();
        protected PZMath_matrix _regionOfInterestMatrix;    // region of interest
        protected StreamWriter _logWriter = null;
        #endregion

        #region Properties
        public string Flag { get { return _flag; } }
        public string LogText { get { return _log; } set { _log = value; } }
        public StreamWriter LogWriter { get { return _logWriter; } set { _logWriter = value; } }
        #endregion

        #region Apply method
        /// <summary>
        /// Apply graylevel/colour image filter
        /// </summary>
        /// <param name="srcImage">source image is Format8bppIndexed or Format24bppRGB</param>
        /// <returns>return image is Format8bppIndexed or Format25bppRGB</returns>
        public Bitmap Apply(Bitmap srcImage)
        {
            Bitmap dstImage;
            if (eee.Sheffield.PZ.Imaging.Image.IsGraylevelImage(srcImage))
            {
                // convert to Format8bppIndexed
                Bitmap copySrcImage = (Bitmap)srcImage.Clone();
                eee.Sheffield.PZ.Imaging.Image.StandardizeImageTo8bbpIndexed(ref copySrcImage);

                // apply graylevel image filter
                dstImage = ApplyGraylevelImageFilter(copySrcImage);
            }
            else
            {
                // conver to Format24bppIndexed
                Bitmap copySrcImage = (Bitmap)srcImage.Clone();
                eee.Sheffield.PZ.Imaging.Image.StandardizeImageTo24bppRGB(ref copySrcImage);

                // apply colour image filter
                dstImage = ApplyColourImageFilter(copySrcImage);
            }

            // standarize return image
            if (eee.Sheffield.PZ.Imaging.Image.IsGraylevelImage(dstImage))
            {
                // convert to Format8Indexed
                Bitmap copyDstImage = (Bitmap)dstImage.Clone();
                eee.Sheffield.PZ.Imaging.Image.StandardizeImageTo8bbpIndexed(ref copyDstImage);
                return copyDstImage;
            }
            else
            {
                // convert to Format24bppRGB
                Bitmap copyDstImage = (Bitmap)dstImage.Clone();
                eee.Sheffield.PZ.Imaging.Image.StandardizeImageTo24bppRGB(ref copyDstImage);
                return copyDstImage;
            }
        } // Apply()
        #endregion

        #region IGraylevelImageFilter method
        public Bitmap ApplyGraylevelImageFilter(Bitmap srcImage) 
        { 
            return ApplyGraylevelImageFilter(srcImage, out _log); 
        }

        public PZMath_matrix ApplyDoubleGraylevelImageFilter(PZMath_matrix srcMatrix) 
        { 
            return ApplyDoubleGraylevelImageFilter(srcMatrix, out _log); 
        }
        protected Bitmap ApplyGraylevelImageFilter(Bitmap srcImage, out string logText)
        {
            if (srcImage.PixelFormat != System.Drawing.Imaging.PixelFormat.Format8bppIndexed)
            {
                Image.StandardizeImageTo8bbpIndexed(ref srcImage);
            }
            PZMath_matrix srcMatrix = _converter.ConvertGraylevelBitmapToMatrix(srcImage);
            PZMath_matrix dstMatrix = ApplyDoubleGraylevelImageFilter(srcMatrix, out logText);
            Bitmap dstImage = _converter.ConvertMatrixToGraylevelBitmap(dstMatrix, _normalize);
            return dstImage;
        }
        protected abstract PZMath_matrix ApplyDoubleGraylevelImageFilter(PZMath_matrix srcMatrix, out string logText);
        #endregion

        #region IColourImageFilter method
        public Bitmap ApplyColourImageFilter(Bitmap srcImage) 
        {
            return ApplyColourImageFilter(srcImage, out _log); 
        }
        public PZMath_matrix[] ApplyDoubleColourImageFilter(PZMath_matrix[] srcMatrix) 
        {
            return ApplyDoubleColourImageFilter(srcMatrix, out _log); 
        }
        protected Bitmap ApplyColourImageFilter(Bitmap srcImage, out string logText)
        {
            PZMath_matrix[] srcMatrixArray = _converter.ConvertColourBitmapToMatrixArray(srcImage);
            PZMath_matrix[] dstMatrixArray = ApplyDoubleColourImageFilter(srcMatrixArray, out logText);
            Bitmap dstImage = _converter.ConvertMatrixArrayToColourBitmap(dstMatrixArray, _normalize);
            return dstImage;
        }
        protected abstract PZMath_matrix[] ApplyDoubleColourImageFilter(PZMath_matrix[] srcMatrixArray, out string logText);
        #endregion

        /// <summary>
        /// Log 
        /// </summary>
        /// <param name="logText"></param>
        public void Log(string logText)
        {
            Console.WriteLine(logText);
            if (_logWriter != null)
            {
                _logWriter.WriteLine(logText);
                _logWriter.Flush();
            }
        } // Log()
    }
}
